﻿using System;
using System.Collections.Generic;

namespace rehot
{
    using rehot.core;

    public class HotEnum
    {
        public HotType Type { get; internal set; }
        public object Value { get; internal set; }
        public string Name { get; internal set; }
        public Type UnderlyingType { get; internal set; }
        public HotEnum(HotType hotType)
        {
            this.Type = hotType;
            if (!hotType.IsType<Enum>()) throw new ArgumentException(hotType.Id);
            UnderlyingType = Enum.GetUnderlyingType(Type._type);
        }
        public HotEnum(Type type) : this(new HotType(type)) { }
        internal HotEnum(HotType hotType, object value) : this(hotType)
        {
            UseEnum(value);
        }
        internal HotEnum UseEnum(object obj)
        {
            if (Type.IsType(obj.GetType().Name)) this.Value = obj;
            else if (obj is HotEnum _value) this.Value = _value.Value;
            else if (obj is HotObject _obj) this.Value = _obj._obj;
            else this.Value = obj;

            Name = Enum.GetName(Type._type, this.Value);
            return this;
        }
        public static HotEnum LoadByType<T>()
        {
            return new HotEnum(typeof(T));
        }
        public HotEnum New(IHotParam value)
        {
            return new HotEnum(Type, Enum.ToObject(Type._type, value.Get()));
        }
        public T New<T>(IHotParam value)where T : Enum
        {
            return Type.New<T>(value);
        }
        public void Set(object value)
        {
            Type.Members.SetObjByMemberId(this.Value, HotMembers.Enum_ValueId, value);
        }
        public IEnumerable<string> AllMemberId()
        {
            foreach (var id in Type.Members.AllEnumMemberId()) yield return id;
        }
        public string ReadNameByMemberId(string id)
        {
            return Type.Members.ReadNameById(id);
        }
        public object ReadValueByMemberId(string id)
        {
            return Type.Members.GetByMemberId(null, id);
        }
        public T ReadValueByMemberId<T>(string id)
        {
            return Type.Members.GetByMemberId<T>(null, id);
        }
        public IEnumerable<KeyValuePair<string, object>> AllMembers()
        {
            foreach (var id in Type.Members.AllEnumMemberId()) yield return new KeyValuePair<string, object>(Type.Members.ReadNameById(id), Convert.ChangeType(Type.Members.GetByMemberId(null, id), UnderlyingType));
        }
        public object GetUnderlyingValue()
        {
            return Convert.ChangeType(this.Value, UnderlyingType);
        }
    }
}
